<?php

/**
 * Clase que implementa el disenno de patrones Singleton.
 * Con este patron de disenno tendremos solo una instancia del
 * usuario actual que solo podra ser crado por medio de la
 * function de clase/estatica usuario(). 
 * Si la primera vez que llamamos a la funcion no existe el la
 * variable $usuario, tratamos de asignarle ...
 * 
 * Nota: nunca se crea una instancia de esta clase por lo que hacemos 
 * al constructor privado. Esto es una de las caracteristicas del 
 * patron de disenno Singleton.
 * 
 * - La clase se llama Usuario_Actual porque la clase al ser statica siempre
 * nos dara una instancia de la clase para el actual usuario autenticado.
 * - Esta clase no extiende la clase Doctrine_Record porque no crea en realidad
 * un modelo.
 * - La variable $usuario contiene al objeto del usuario autenticado. Para usarla
 * lo hacemos a traves de la clase Usuario_Actual::usuario() 
 * @author guido
 *
 */
class Current_User {
	
	private static $user;
	
	private function __construct() {}
	
	public static function user() {
	  // Use $this to refer to the current object. 
	  // Use self to refer to the current class. 
	  // In other words, use $this->member for non-static members, use self::$member for static members.
		if(!isset(self::$user)) {
			
			$CI =& get_instance();
			
			if (!$user_id = $CI->session->userdata('user_id')) {
				return FALSE;
			}
			
			if (!$u = Doctrine::getTable('User')->find($user_id)) {
				return FALSE;
			}
			
			self::$user = $u;
		}
		
		return self::$user;
	}
	
	/**
	 * Authenticate and validate the user.
	 * @param $username
	 * @param $password
	 * @return unknown_type
	 */
	public static function authenticate($username, $password) {
		// get User object by username 
		if ($u = Doctrine::getTable('User')->findOneByUsername($username)) {
			
			// password match
			$CI =& get_instance();
			$session_id = $CI->session->userdata('session_id');
			$userPassword = md5($session_id.$u->password);
			if ($userPassword == $password) {
				
				$userdata = array(
        	'username'  => $u->username,
					'user_id'		=> $u->uid,
          'email'     => $u->email,
					'roles'			=> $u->getRolesName(),
          'logged_in' => TRUE
        );
        $CI->session->set_userdata($userdata);

				//$CI->session->set_userdata('user_id', $u->uid);
				self::$user = $u;
				self::authenticateFinalize();
				return TRUE;
			}
			
			unset($u_input);
		}
		
		// login failed
		return FALSE;
	}
		
	public function __clone() {
		trigger_error('Clone is not allowed.', E_USER_ERROR);
	}
	
	/**
	 * Finalize the login process. Must be called when logging in a user.
	 */
	private static function authenticateFinalize() {
	  // Update the user table timestamp noting user has logged in.
	  // This is also used to invalidate one-time login links.
	  self::$user->login = time();
	  self::$user->save();
	}
	
	/**
	 * Determine whether the user has a given privilege.
	 *
	 * @param $string
	 *   The permission, such as "administer user", being checked for.
	 * @param $reset
	 *   (optional) Resets the user's permissions cache, which will result in a
	 *   recalculation of the user's permissions. This is necessary to support
	 *   dynamically added user roles.
	 *
	 * @return
	 *   Boolean TRUE if the current user has the requested permission.
	 *
	 * All permission checks in Drupal should go through this function. This
	 * way, we guarantee consistent behavior, and ensure that the superuser
	 * can perform all actions.
	 */
	public static function hasAccessFor($string, $reset = FALSE) {
		static $permissions = array();
		$user_id = isset(self::$user) ? self::$user->uid : ANONYMOUS_USER_ID;
		
	  if ($reset) {
	    $permissions = array();
	  }
	
	  // User #2 has all privileges:
	  /*
	  if ($user_id == ADMINISTRATOR_ID) {
	    return TRUE;
	  }
	  */
	
		if (!isset($permissions[$user_id])) {
		  /*
			select p.permission from sismapc.permission p 
				inner join sismapc.roles_permissions rp on rp.permission_id = p.id
				inner join sismapc.role r on rp.role_id = r.id
				inner join sismapc.users_roles ur on r.id = ur.role_id
				inner join sismapc.user u on ur.user_id = u.uid
				where u.uid = 2; 
			*/
	
			$conn = Doctrine_Manager::connection();
			
			$query = 'select p.permission from sismapc.permission p 
				inner join sismapc.roles_permissions rp on rp.permission_id = p.id
				inner join sismapc.role r on rp.role_id = r.id
				inner join sismapc.users_roles ur on r.id = ur.role_id
				inner join sismapc.user u on ur.user_id = u.uid
				where u.uid = '.$user_id;
			
			$statement = $conn->prepare($query); 
			$statement->execute(); 
			$results = $statement->fetchAll(); 
		  $perms = array();
		  foreach( $results as $result ) {
		   	$perms[] = $result['permission'];	
		  }
		  $permissions[$user_id] = array_flip($perms);
		} 
	  
  	return isset($permissions[$user_id][$string]);
	}
	
}
